-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add SSL options to mssql #33071
add SSL options to mssql #33071
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎ 1 Ignored Deployment
|
Current dependencies on/for this PR:
This stack of pull requests is managed by Graphite. |
Before Merging a Connector Pull RequestWow! What a great pull request you have here! 🎉 To merge this PR, ensure the following has been done/considered for each connector added or updated:
If the checklist is complete, but the CI check is failing,
|
case "unencrypted" -> additionalParameters.add("encrypt=false"); | ||
case "unencrypted" -> { | ||
additionalParameters.add("encrypt=false"); | ||
additionalParameters.add("trustServerCertificate=true"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only added for clarity. By default, encrypt=false implies trustServerCertificate=true.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
trustServerCertificate is trust all essentially.
This will trust any server certificate. I assume for the exchange of credentials which is still encrypted event when encrypt=false
(you mentioned this offline)
case "encrypted_trust_server_certificate" -> { | ||
additionalParameters.add("encrypt=true"); | ||
additionalParameters.add("trustServerCertificate=true"); | ||
} | ||
case "encrypted_verify_certificate" -> { | ||
additionalParameters.add("encrypt=true"); | ||
additionalParameters.add("trustServerCertificate=false"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added for clarity. By default, encrypt=true implies trustServerCertificate=false
|
||
// trust store location code found at https://stackoverflow.com/a/56570588 | ||
final String trustStoreLocation = Optional |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this was really not doing anything. If anything, it'd guarantee that the connection would fail (because with this, the sever certificate would have to be signed by one of the root authorities in the default trust store)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the old behavior is equivalent to not pushing anything as a trustStorelocation JDBC parameer
char[] pwdArray = password.toCharArray(); | ||
final File trustStoreFile; | ||
try { | ||
trustStoreFile = File.createTempFile("mssqlTrustStoreFile", "jks"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The MSSQL driver takes a trust store file location as a parameter. Unfortunately, such a file is binary, which means it can't be uploaded from the current UI. It really doesn't matter, since a certificate is just as good, as long as we have either the server certificate that of the CA that signed the server certificate
@@ -4,7 +4,7 @@ | |||
"$schema": "http://json-schema.org/draft-07/schema#", | |||
"title": "MSSQL Source Spec", | |||
"type": "object", | |||
"required": ["host", "port", "database", "username"], | |||
"required": ["host", "port", "database", "username", "password"], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the password is required in the parameter parsing logic in MssqlSource.java. Making it mandatory in the UI as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this a breaking change? What is the expected behavior here?
I'm thinking of existing configs for example saved without a password
@@ -90,7 +90,7 @@ | |||
{ | |||
"title": "Encrypted (verify certificate)", | |||
"description": "Verify and use the certificate provided by the server.", | |||
"required": ["ssl_method", "trustStoreName", "trustStorePassword"], | |||
"required": ["ssl_method"], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unless I'm missing something, the previous required fields didn't even exist in the spec.json. Removing them...
bd13cbd
to
2bee629
Compare
@@ -3,4 +3,5 @@ | |||
"port": 5555, | |||
"database": "default", | |||
"username": "default" | |||
"password": "default" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
now that the password is a mandatory field, it needs to be added here too
super(testDatabase); | ||
with(JdbcUtils.JDBC_URL_PARAMS_KEY, "loginTimeout=2"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this allows us to reduce the test running times from 1m to 2seconds for the tests that are expecting a failure to connect to the DB!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we always want to set this for all test cases, though? I don't have a problem with it. I took a more conservative approach with maybeSetShorterConnectionTimeout
but that conservatism may not have been warranted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no problems with it so far...
8764627
to
e5150a9
Compare
.../connectors/source-mssql/src/main/java/io/airbyte/integrations/source/mssql/MssqlSource.java
Show resolved
Hide resolved
case "unencrypted" -> additionalParameters.add("encrypt=false"); | ||
case "unencrypted" -> { | ||
additionalParameters.add("encrypt=false"); | ||
additionalParameters.add("trustServerCertificate=true"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
trustServerCertificate is trust all essentially.
This will trust any server certificate. I assume for the exchange of credentials which is still encrypted event when encrypt=false
(you mentioned this offline)
6fe667a
to
828771e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand all of this but for what I do, I don't have any significant objections.
@@ -9,7 +9,7 @@ data: | |||
connectorSubtype: database | |||
connectorType: source | |||
definitionId: b5ea17b1-f170-46dc-bc31-cc744ca984c1 | |||
dockerImageTag: 3.1.0 | |||
dockerImageTag: 3.1.1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The CI is going to complain about a missing release note.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably go to the latest 3.5.0
} | ||
|
||
@ParameterizedTest | ||
@EnumSource(CertificateKey.class) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yesss! Though perhaps having two enums, one for valid and another for invalid certificates, might be preferable for expressing these tests.
.build(); | ||
try { | ||
AirbyteCatalog catalog = new MssqlSource().discover(config); | ||
assertTrue(certificateKey.isValid); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps it's just me but I would find some branching logic if (certificateKey.isValid) { ...
easier to read here. Do I understand correctly that we expect discover to throw iff !isValid?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no we expect discover to work for valid certificates, and fail for invalid ones. I will split this test in 2 to be clearer
public void withSslCertificates(MSSQLServerContainer<?> container) { | ||
// yes, this is uglier than sin. The reason why I'm doing this is because there's no command to | ||
// reload a SqlServer config. So I need to create all the necessary files before I start the | ||
// SQL server. Hence this horror |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whatever it takes!
EOF | ||
} && /opt/mssql/bin/sqlservr | ||
""", | ||
"{hostName}", container.getHost()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fine by me but perhaps using an env var to inject the host name would be simpler? Then again perhaps not, I don't know. Just a thought.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, I guess that would work too. Even though I have more refactors in mind.
super(testDatabase); | ||
with(JdbcUtils.JDBC_URL_PARAMS_KEY, "loginTimeout=2"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we always want to set this for all test cases, though? I don't have a problem with it. I took a more conservative approach with maybeSetShorterConnectionTimeout
but that conservatism may not have been warranted.
e9d0acb
to
19bf49f
Compare
19bf49f
to
366b329
Compare
7901560
to
d5e1af5
Compare
@@ -1 +1 @@ | |||
version=0.8.0 | |||
version=0.8.1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
make sure mssql points to the latest - 0.8.2(?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done (0.10.4)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks Stephane.
Just make sure all versions are aligned before merging,
d5e1af5
to
ed91686
Compare
/publish-java-cdk
|
Updated and merged as discussed during team standup earlier this week. |
Co-authored-by: Marius Posta <[email protected]>
Co-authored-by: Marius Posta <[email protected]>
This is adding extra support for SSL options in our MS SQL source.
The MSSQL options are a bit different than postgres and MySql,so I'm not using their common logic. The flip side is that this change is not breaking compatibility!
We're basically adding the ability to send a certificate. (of the server or of the CA that signed the server certificate), and the ability to override the hostname used to connect in order to match the hostname of the server certificate.
While doing those changes, I also noticed that the password was actually mandatory in MsSqlSource, even though it wasn't marked as such in the spec.jsob.
The tests try to go the extra mile by connecting to the SQL server by IP rather than hostname, which triggers a failure to validate the certificate's host. And There's an extra test that connects by IP and passes the certificate's hostname in the spec, so the loop is closed.
On minor thing to note is that the MS SQL JDBC driver expects a keystore (technically a keystore file path), but we can't pass those through the current UI (because a key store is not a text file). So instead, we're passing a certificate, and the MsSqlSource converts that into a keystore file that is materialized in the container and its path is passed to the JDBC driver
tests are passing, connector version is bumpted
Resolves #30004